package com.lalameow.researchstation.screen.widget

import com.lalameow.researchstation.network.TechnologyCategoriesNetwork
import com.lalameow.researchstation.screen.ResearchStationScreen
import com.lalameow.researchstation.util.MinecraftClient
import com.lalameow.researchstation.util.Offset
import com.lalameow.researchstation.util.x
import com.lalameow.researchstation.util.y
import com.mojang.blaze3d.systems.RenderSystem
import net.fabricmc.api.EnvType
import net.fabricmc.api.Environment
import net.minecraft.client.gui.DrawableHelper
import net.minecraft.client.render.item.ItemRenderer
import net.minecraft.client.util.math.MatrixStack
import net.minecraft.client.util.math.Rect2i
import net.minecraft.util.Identifier

@Environment(EnvType.CLIENT)
internal class ResearchTabWidget(
    val category: TechnologyCategoriesNetwork.Packet,
    private val itemRenderer: ItemRenderer,
    private var position: Offset = 0 to 0,
    private var direction: Direction = Direction.TOP,
    private var offset: Int = 0
) : DrawableHelper() {
    companion object {
        const val TAB_WIDTH = 28
        const val TAB_HEIGHT = 32
    }

    val background: Identifier?
        get() = category.background
    private val iconWidget = DynamicItemIconWidget(category.icon.toList())

    fun MatrixStack.draw(x: Int, y: Int, mouse: Offset, selected: Boolean) {
        RenderSystem.enableDepthTest()
        drawBackground(selected)
        itemRenderer.drawIcon(x, y)
        if (isMouseOn(x, y, mouse)) {
            drawTooltip(mouse.x - x, mouse.y - y)
        }
    }

    private fun MatrixStack.drawBackground(selected: Boolean) {
        RenderSystem.setShaderTexture(0, ResearchStationScreen.TABS_TEXTURE)
        push()
        translate(position.x.toDouble(), position.y.toDouble(), 0.0)
        val textureRect = direction.rect(selected)
        drawTexture(
            this,
            0,
            0,
            textureRect.x + offset,
            textureRect.y,
            textureRect.width,
            textureRect.height
        )
        pop()
    }

    private fun ItemRenderer.drawIcon(x: Int, y: Int) {
        with(iconWidget) {
            draw(
                x + direction.iconOffset.x + position.x,
                y + direction.iconOffset.y + position.y
            )
        }
    }

    private fun MatrixStack.drawTooltip(mouseX: Int, mouseY: Int) {
        val lines = mutableListOf(category.name)
        if (category.description != null) lines += category.description
        MinecraftClient.currentScreen?.renderTooltip(
            this,
            lines,
            mouseX,
            mouseY
        )
    }

    fun isMouseOn(screenX: Int, screenY: Int, mouse: Offset): Boolean {
        val i = screenX + position.x
        val j = screenY + position.y
        val rect = direction.rect(false)
        return mouse.x in i until (i + rect.width) && mouse.y in j until (j + rect.height)
    }
}

@Environment(EnvType.CLIENT)
internal enum class Direction(
    private val normal: Rect2i,
    private val selected: Rect2i,
    val offset: Int,
    val iconOffset: Offset
) {
    TOP(
        Rect2i(0, 0, ResearchTabWidget.TAB_WIDTH, 30),
        Rect2i(
            0,
            31,
            ResearchTabWidget.TAB_WIDTH,
            ResearchTabWidget.TAB_HEIGHT
        ),
        ResearchTabWidget.TAB_WIDTH,
        6 to 9
    ),
    BOTTOM(
        Rect2i(
            84,
            0,
            ResearchTabWidget.TAB_WIDTH,
            30
        ),
        Rect2i(84, 31, ResearchTabWidget.TAB_WIDTH, ResearchTabWidget.TAB_HEIGHT),
        ResearchTabWidget.TAB_WIDTH,
        6 to 6
    ),
    LEFT(
        Rect2i(0, 63, ResearchTabWidget.TAB_HEIGHT, ResearchTabWidget.TAB_WIDTH),
        Rect2i(0, 92, ResearchTabWidget.TAB_HEIGHT, ResearchTabWidget.TAB_WIDTH),
        ResearchTabWidget.TAB_HEIGHT,
        10 to 5
    ),
    RIGHT(
        Rect2i(96, 63, ResearchTabWidget.TAB_HEIGHT, ResearchTabWidget.TAB_WIDTH),
        Rect2i(96, 91, ResearchTabWidget.TAB_HEIGHT, ResearchTabWidget.TAB_WIDTH),
        ResearchTabWidget.TAB_HEIGHT,
        6 to 5
    );

    fun rect(selected: Boolean): Rect2i {
        val rect = if (selected) this.selected else normal
        return Rect2i(rect.x, rect.y, rect.width, rect.height)
    }
}
